#include "t_box_seek_manager.h"
#include "t_box.h"

int T_Box_Seek_Manager::pendingRequest()
{
    T_ATOMIC_LOCKER(v_atom_locker, &m_request_atomic);
    return m_request_queue.size();
}
void T_Box_Seek_Manager::enqueueRequest(int a_timing)
{
    T_ATOMIC_LOCKER(v_atom_locker, &m_request_atomic);
    m_request_queue.enqueue(a_timing);
    this->wakeAll();
}
int T_Box_Seek_Manager::dequeueRequest()
{
    T_ATOMIC_LOCKER(v_atom_locker, &m_request_atomic);
    int v_result = m_request_queue.last();
    m_request_queue.clear();
    return v_result;
}
qint64 T_Box_Seek_Manager::maxTiming()
{
    T_ATOMIC_LOCKER(v_atom_locker, &m_request_atomic);
    return m_max_timing;
}
void T_Box_Seek_Manager::registerTiming(qint64 a_timing)
{
    T_ATOMIC_LOCKER(v_atom_locker, &m_request_atomic);
    if(m_max_timing == LONG_LONG_MAX)
    {
        return;
    }
    if(a_timing == LONG_LONG_MAX)
    {
        m_max_timing = LONG_LONG_MAX;
    }
    else
    {
        int v_hedge = T_Box::PLAYER_HEAD_HEADGE;
        if(a_timing>(m_max_timing+v_hedge))
        {
            m_max_timing = a_timing-v_hedge;
        }
    }
}

qint64 T_Box_Seek_Manager::seekableDuration()
{
    T_ATOMIC_LOCKER(v_atom_locker, &m_request_atomic);
    if(m_max_timing==LONG_LONG_MAX)
    {
        if(m_duration<0) return LONG_LONG_MAX;
        return m_duration;
    }
    qint64 v_timing = m_max_timing - T_Box::PLAYER_HEAD_HEADGE;
    if(v_timing<0) v_timing=0;
    return v_timing;
}

qint64 T_Box_Seek_Manager::endlessDuration(qint64 a_timing)
{
    T_ATOMIC_LOCKER(v_atom_locker, &m_request_atomic);
    if(m_max_timing==LONG_LONG_MAX)
    {
        return LONG_LONG_MAX;
    }
    qint64 v_ahead = m_max_timing - a_timing;
    if(v_ahead < 0)
    {
        v_ahead = 0;
    }
    return v_ahead;
}

void T_Box_Seek_Manager::addSeekable(T_Box_Seekable *a_seekable)
{
    T_ATOMIC_LOCKER(v_atom_locker, &m_request_atomic);
    m_seekable_list.append(a_seekable);
}

qint64 T_Box_Seek_Manager::seek(qint64 a_msec)
{
    //T_ATOMIC_LOCKER(v_atom_locker, &m_request_atomic); //N.G.: don't do this
    T_WRITE_LOCKER(v_seek_locker, this);
    //qint64 v_max_timing = this->maxTiming();
    qint64 v_max_timing = this->seekableDuration();
    if(a_msec > v_max_timing) a_msec = v_max_timing;
    qint64 v_result = -1;
    foreach(T_Box_Seekable *v_stream, m_seekable_list)
    {
        qint64 v_timing = v_stream->seekMe(this, a_msec);
        if(v_timing < 0) continue;
        if(v_result < 0) v_result = v_timing;
        v_result = qMin(v_result, v_timing);
    }
    this->T_Clock::reset(); //FIXME: rset(), elapsed() ==> internal use
    if(v_result < 0) return -1;
    this->timeline()->setElapsed(v_result);
    return v_result;
}
